package mop.gui;

import java.util.List;

import javax.swing.JOptionPane;
import mop.controller.*;
import mop.gui.admin.AdminWindow;
import mop.gui.main.MainWindow;
import mop.gui.project.CreateProjectDialog;
import mop.gui.project.ProjectDetailsDialog;
import mop.gui.resource.CreateResourceDialog;
import mop.gui.task.TaskDetailsDialog;
import mop.gui.task.TaskStatusDialog;
import mop.gui.main.LoginDialog;
import mop.gui.reservation.MakeReservationDialog;
import mop.gui.task.AssignTaskDialog;
import mop.gui.task.CreateTaskDialog;
import mop.gui.task.SelectTaskTypeDialog;
import mop.model.project.ProjectInterface;
import mop.model.task.TaskInterface;
import mop.model.task.tasktype.TaskTypeInterface;

/**
 * Main GUI class.
 *
 * @author  MOP Team 7
 */
public class GUI implements ControllerVisitor
{
    /**
     * Constructor.
     *
     * @effect  Sets all given controllers.
     */
    public GUI(List<UseCaseController> controllers)
    {
        this.controllers = controllers;

    	for (UseCaseController ucc : controllers)
    	{
    		ucc.visit(this);
    	}
    }

    /***************************************************************************
     *                  			Main Window
     ***************************************************************************/

    /**
     * There can only be 1 main window!
     */
    private MainWindow mainWindow;

    /**
     * Returns the main window.
     *
     * @return	MainWindow
     */
    public MainWindow getMainWindow()
    {
    	return this.mainWindow;
    }

    /**
     * Opens a MainWindow.
     */
    public void showMainWindow()
    {
    	if (this.mainWindow == null)
    	{
    		this.mainWindow = new MainWindow(this, controllers);
    	}

    	this.mainWindow.setVisible(true);
    }

    /**
     * Closes it.
     */
    public void closeMainWindow()
    {
        if (this.mainWindow != null) {
            this.mainWindow.dispose();
            this.mainWindow = null;
        }
    }

    /***************************************************************************
     *                             Logging in
     ***************************************************************************/

    /**
     * Opens a LoginDialog.
     */
    public void showLoginDialog()
    {
        (new LoginDialog(this, this.loginUserController)).setVisible(true);
    }

    /***************************************************************************
     *                              Admin
     ***************************************************************************/

    /**
     * Opens an admin window.
     */
    public void showAdminWindow()
    {
        (new AdminWindow(this, this.changeClockController, this.createUserController)).setVisible(true);
    }

    /***************************************************************************
     *                              Projects
     ***************************************************************************/

    /**
     * Opens a CreateProjectDialog.
     */
    public void showCreateProjectDialog()
    {
        (new CreateProjectDialog(this, this.createProjectController)).setVisible(true);
    }

    /**
     * Opens a ProjectDetailsDialog.
     *
     * @param   project
     *          ProjectInterface.
     */
    public void showProjectDetailsDialog(ProjectInterface project)
    {
        (new ProjectDetailsDialog(this, project)).setVisible(true);
    }

    /***************************************************************************
     *                              Tasks
     ***************************************************************************/

    /**
     * Opens a dialog for selecting a task type.
     */
    public void showSelectTaskTypeDialog()
    {
        (new SelectTaskTypeDialog(this, this.createTaskController)).setVisible(true);
    }

    /**
     * Opens a OldCreateTaskDialog.
     *
     * @param   TaskTypeInterface
     */
    public void showCreateTaskDialog(TaskTypeInterface taskType)
    {
        (new CreateTaskDialog(this, this.createTaskController, taskType)).setVisible(true);
    }

    /**
     * Opens a AssignTaskDialog.
     *
     * @param   TaskInterface
     */
    public void showAssignTaskDialog(TaskInterface task)
    {
        (new AssignTaskDialog(this, this.assignTaskToProjectController, task)).setVisible(true);
    }

    /**
     * Opens a TaskDetailsDialog.
     *
     * @param   task
     *          TaskInterface.
     */
    public void showTaskDetailsDialog(TaskInterface task)
    {
        (new TaskDetailsDialog(this, this.modifyTaskDetailsController, task)).setVisible(true);
    }

    /**
     * Opens a TaskStatusDialog.
     *
     * @param   task
     *          TaskInterface.
     */
    public void showTaskStatusDialog(TaskInterface task)
    {
        (new TaskStatusDialog(this, this.updateTaskStatusController, task)).setVisible(true);
    }

    /***************************************************************************
     *                              Resources
     ***************************************************************************/

    /**
     * Opens a CreateResourceDialog.
     *
     * @param   mainWindow
     *          Parent JFrame.
     */
    public void showCreateResourceDialog()
    {
        (new CreateResourceDialog(this, this.createResourceController)).setVisible(true);
    }

    /***************************************************************************
     *                              Reservations
     ***************************************************************************/

    /**
     * Opens a MakeReservationDialog.
     *
     * @param   task
     *          TaskInterface.
     */
    public void showMakeReservationDialog(TaskInterface task)
    {
        (new MakeReservationDialog(this, this.makeResourceReservationController, task)).setVisible(true);
    }

    /***************************************************************************
     *                          Handling messages
     ***************************************************************************/

    /**
     * Handles an exception by showing the error message.
     *
     * @param   exception
     *          Throwable
     */
    public void handleError(Throwable exception)
    {
        handleError(exception.toString());
        exception.printStackTrace(System.err); // FOR DEBUGGING PURPOSES!
    }

    /**
     * Shows an error message.
     *
     * @param   exception
     *          Throwable
     */
    public void handleError(String e)
    {
        JOptionPane.showMessageDialog(null, e, "Error", JOptionPane.ERROR_MESSAGE);
    }

    /**
     * Shows a "success" message.
     *
     * @param   s
     *          String
     */
    public void handleSuccess(String s)
    {
        JOptionPane.showMessageDialog(null, s, "Success", JOptionPane.INFORMATION_MESSAGE);
    }

    /***************************************************************************
     *                          Controller references
     ***************************************************************************/

    private List<UseCaseController> controllers;
    private AssignTaskToProjectController assignTaskToProjectController;
    private ChangeClockController changeClockController;
    private CreateProjectController createProjectController;
    private CreateResourceController createResourceController;
    private CreateTaskController createTaskController;
    private CreateUserController createUserController;
    private FocusWorkController focusWorkController;
    private LoginUserController loginUserController;
    private MakeResourceReservationController makeResourceReservationController;
    private ModifyTaskDetailsController modifyTaskDetailsController;
    private RemoveProjectController removeProjectController;
    private RemoveTaskController removeTaskController;
    private UpdateTaskStatusController updateTaskStatusController;

    @Override
    public void action(AssignTaskToProjectController c)
    {
            this.assignTaskToProjectController = c;
    }

    @Override
    public void action(ChangeClockController c)
    {
            this.changeClockController = c;
    }

    @Override
    public void action(CreateProjectController c)
    {
            this.createProjectController = c;
    }

    @Override
    public void action(CreateResourceController c)
    {
            this.createResourceController = c;
    }

    @Override
    public void action(CreateTaskController c)
    {
            this.createTaskController = c;
    }

    @Override
    public void action(CreateUserController c)
    {
            this.createUserController = c;
    }

    @Override
    public void action(FocusWorkController c)
    {
            this.focusWorkController = c;
    }

    @Override
    public void action(MakeResourceReservationController c)
    {
            this.makeResourceReservationController = c;
    }

    @Override
    public void action(ModifyTaskDetailsController c)
    {
            this.modifyTaskDetailsController = c;
    }

    @Override
    public void action(RemoveTaskController c)
    {
            this.removeTaskController = c;
    }

    @Override
    public void action(UpdateTaskStatusController c)
    {
            this.updateTaskStatusController = c;
    }

    @Override
    public void action(LoginUserController c)
    {
            this.loginUserController = c;
    }

    @Override
    public void action(RemoveProjectController c)
    {
            this.removeProjectController = c;
    }
}